package gocache

import (
	"sync"
	"time"
)

type CacheOperator interface {
	SetWithTTL(k string, v any, ttl time.Duration)
	Del(k string)
	Get(k string) (v any, ok bool)
	Wait()
}

var (
	defCacheLk       sync.RWMutex
	defCache         CacheOperator
	cacheFactoryFunc func() CacheOperator
)

func init() {
	SetDefault(nil)
	SetCacheFactoryFunc(nil)
}

func SetDefault(c CacheOperator) {
	if c == nil {
		c = NewMapCache()
	}
	defCacheLk.Lock()
	defCache = c
	defCacheLk.Unlock()
}

func NewCache() CacheOperator {
	return cacheFactoryFunc()
}

func SetCacheFactoryFunc(fn func() CacheOperator) {
	if fn == nil {
		fn = NewMapCache
	}
	cacheFactoryFunc = fn
}

func Default() CacheOperator {
	defCacheLk.RLock()
	defer defCacheLk.RUnlock()
	return defCache
}

func Set(key string, v any) {
	SetWithTTL(key, v, 0)
}

func Delete(key string) {
	Default().Del(key)
}

func SetWithTTL(key string, v any, ttl time.Duration) {
	Default().SetWithTTL(key, v, ttl)
}

func WaitSucc() {
	Default().Wait()
}

func Get(key string) (any, bool) {
	return Default().Get(key)
}

func GetOrDefault(key string, def any) any {
	if v, ok := Default().Get(key); ok {
		return v
	}
	return def
}
